public with sharing class GeneratePlansForGroupOfRepsVF {
	
	public String status {get; set;}
	public String planGroupName {get; set;}
	public Sales_Contract__c sc {get; set;}
	public Batch__c batch {get; set;} 
	public Sales_Contract__c[] contracts {get; set;}
	public BatchedUser__c[] buList {get; set;}
    public Integer totalDataSources {get; set;}
    public Integer planDocsCreated {get; set;}
	public Boolean inputFlag {get; set;}
	public Boolean outputFlag {get; set;}
			
    private String formSoql = '';
    private String fieldName = '';     
	private String batchId; 
	private Map<ID, String > templateAttachmentMap;
	private Set<ID> userSet;
    public List<Sales_Contract__c> planDocumentsList {get;set;}
	private DataAccessControlUtil dacu = new DataAccessControlUtil();
    private String[] roFields {get; set;} 
    private Set<String> allowedROFields {get; set;}
    private Map<String, Schema.SObjectField> reportManagerSObjectFieldMap = new Map<String, Schema.SObjectField>();  
    	
	public GeneratePlansForGroupOfRepsVF()
	{
		sc = new Sales_Contract__c();
		status = 'Draft';
		inputFlag = true;
		outputFlag = false;
		batchId = ApexPages.currentPage().getParameters().get('bcId');
		if(batchId != null)
		{
			
			templateAttachmentMap = new Map<ID, String>();
			userSet = new Set<ID>();
			buList = [select User__c, User__r.Name, User__r.UserRole.Name, Template__c, Template__r.Name, User_Title__c from BatchedUser__c where TemplateId__c != null and batchid__c = :batchId];
			String[] tempAttachmentList = null;
			for(BatchedUser__c bu: buList)
			{
				userSet.add(bu.User__c);
				if(templateAttachmentMap.get(bu.Template__c) == null)
				{
					tempAttachmentList = GenerateUtil.getTemplateAttachments(bu.Template__c);
					if(tempAttachmentList != null)
						templateAttachmentMap.put(bu.Template__c, tempAttachmentList[0]);	
				}
			}
			
		}
	}
	
	public Pagereference startGeneration()
	{
        if(planGroupName == '')
        {
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.info, 'Please enter Plan Group Name.'));
            return null;    
        }
        if(sc.Effective_Start_Date__c == null)
        {
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.info, 'Please enter Effective Start Date.'));
            return null;    
        }
        if(sc.Effective_End_Date__c == null)
        {
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.info, 'Please enter Effective End Date.'));
            return null;    
        }
        if(sc.RequiredReturnDate__c == null)
        {
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.info, 'Please enter Required Acceptance Date.'));
            return null;    
        }
        if(sc.Effective_Start_Date__c > sc.Effective_End_Date__c)
        {
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.info, 'Effective Start Date should be earlier than Effective End Date.'));
            return null;    
        }
        if(sc.RequiredReturnDate__c > sc.Effective_End_Date__c)
        {
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.info, 'Required Acceptance Date should be earlier or equal to Effective End Date.'));
            return null;    
        }

        List<User> participantsWithNoManagerAssigned = new List<User>();   
        List<User> inactiveParticipants = new List<User>(); 
		try
		{
	        totalDataSources = userSet.size();
	        planDocsCreated = 0;
			inputFlag = false;
			outputFlag = true;
	        
            Reporting_Manager__c[] rmList = [select reporting_manager__c from reporting_manager__c];
            fieldName = rmList[0].Reporting_Manager__c;
            if(fieldName != null)
            {}
            else
            	fieldName = 'ManagerId';
            SObject so = null;
            for(User[] localUserList: Database.query('select Id, Name, FirstName, LastName,UserRole.Name, Title, IsActive, '+fieldName+' from User where id in :userSet '))
            {
                for(User u: localUserList)
                {
                    so = u;
                    if(so.get(fieldName) == null)
                        participantsWithNoManagerAssigned.add(u);
                    if(so.get('IsActive') == false)
                        inactiveParticipants.add(u);
                }
            }
            
            if(participantsWithNoManagerAssigned.size() > 0)
            {
                for(User u: participantsWithNoManagerAssigned)
                {
                    userSet.remove(u.id);                    
                    userSet.remove(u.id);                   
                    userSet.remove(u.id);
                    userSet.remove(u.id);
                    userSet.remove(u.id);
                }
            }
            
            if(inactiveParticipants.size() > 0)
            {
                for(User u: inactiveParticipants)
                {
                    userSet.remove(u.id);                    
                    userSet.remove(u.id);                   
                    userSet.remove(u.id);
                    userSet.remove(u.id);
                    userSet.remove(u.id);
                }
            }
            
			
            Task[] tasksList = new Task[]{};
	        Approvers__c[] approver = null;
	        Date dt = Date.today();
	        planDocumentsList = new List<Sales_Contract__c>();
	        
	        String[] approverExpectedFields = new String[]{'Template__c','Final_Approver__c','Final_Approver_Date__c','Level1__c','Level2__c','Level3__c','Level4__c','Level5__c','Level6__c','Level7__c','Level8__c','Level9__c','Level10__c','Level11__c','Level12__c','Level13__c','Level14__c','Level15__c','Level1_Due_Date__c','Level2_Due_Date__c','Level3_Due_Date__c','Level4_Due_Date__c','Level5_Due_Date__c','Level6_Due_Date__c','Level7_Due_Date__c','Level8_Due_Date__c','Level9_Due_Date__c','Level10_Due_Date__c','Level11_Due_Date__c','Level12_Due_Date__c','Level13_Due_Date__c','Level14_Due_Date__c','Level15_Due_Date__c'};
	        SObject appObj = new Approvers__c();
	        Map<String, Schema.SObjectField> approverFieldMap = dacu.getFieldMap(appObj);
	        Set<String> allowedROFields = dacu.getAccessibleFields(appObj, approverFieldMap, approverExpectedFields);
	        String formSoql = '';
            batch = [SELECT Name, Status__c, TotalContracts__c, RemainingContracts__c, Effective_Start_Date__c, Effective_End_Date__c,StartTime__c, EndTime__c from Batch__c b where  b.Id = :batchId];
            batch.StartTime__c = datetime.now();
			update batch;	        
			
            Remote_IP_Address__c[] ripList = [select Is_Global_Approvers_Used__c, Plan_Document_Name__c from Remote_IP_Address__c];
			
	        if(!allowedROFields.isEmpty())
	        {
	            formSoql = 'Select ';
	            for(String roField: allowedROFields)
	            {
	                formSoql += roField+', ';
	            }
	            formSoql = formSoql.substring(0, formSoql.length() - 2);
	            
	            //Not filtering using the ownerId as the records are used by all Admins. 
	            formSoql += ' from Approvers__c ';
	            
	            //get Accessible fields for the Where clause filter
	            approverExpectedFields = new String[]{'Template__c'};
	            allowedROFields = dacu.getAccessibleFields(appObj, approverFieldMap, approverExpectedFields);
	            if(!allowedROFields.isEmpty())
	            {
	                formSoql += ' where ';
	                for(String roField: allowedROFields)
	                {
	                  	formSoql += roField+' = null order by CreatedDate desc limit 1 ';
	                }
	                
	            }
	            approver = Database.query(formSoql);
	        }        
	
		    for(CallidusDataSource__c[] src : [SELECT Name,FirstName__c,LastName__c,SyncDate__c,IsActive__c, UserID__c,UserRoleId__c,UserRoleName__c,User_Title__c, Name1__c, Name2__c, Name3__c, Name4__c, Name5__c, Name6__c, Name7__c, Name8__c, Name9__c, Name10__c, Name11__c, Name12__c, Name13__c, Name14__c, Name15__c, Name16__c, Name17__c, Name18__c, Name19__c, Name20__c, Name21__c, Name22__c, Name23__c, Name24__c, Name25__c, Name26__c, Name27__c, Name28__c, Name29__c, Name30__c, Value1__c, Value2__c, Value3__c, Value4__c, Value5__c, Value6__c, Value7__c, Value8__c, Value9__c, Value10__c, Value11__c, Value12__c, Value13__c, Value14__c, Value15__c, Value16__c, Value17__c, Value18__c, Value19__c, Value20__c, Value21__c, Value22__c, Value23__c, Value24__c, Value25__c, Value26__c, Value27__c, Value28__c, Value29__c, Value30__c, Name31__c, Name32__c, Name33__c, Name34__c, Name35__c, Name36__c, Name37__c, Name38__c, Name39__c, Name40__c, Name41__c, Name42__c, Name43__c, Name44__c, Name45__c, Name46__c, Name47__c, Name48__c, Name49__c, Name50__c, Name51__c, Name52__c, Name53__c, Name54__c,Name55__c,Name56__c,Name57__c,Name58__c,Name59__c,Name60__c,Name61__c,Name62__c,Name63__c,Name64__c,Name65__c,Name66__c,Name67__c,Name68__c,Name69__c,Name70__c,Name71__c,Name72__c,Name73__c,Name74__c,Name75__c,Name76__c,Name77__c,Name78__c,Name79__c,Name80__c,Name81__c,Name82__c,Name83__c,Name84__c,Name85__c,Name86__c,Name87__c,Name88__c,Name89__c,Name90__c,Value31__c, Value32__c, Value33__c, Value34__c, Value35__c, Value36__c, Value37__c, Value38__c, Value39__c, Value40__c, Value41__c, Value42__c, Value43__c, Value44__c, Value45__c, Value46__c, Value47__c, Value48__c, Value49__c, Value50__c, Value51__c, Value52__c, Value53__c, Value54__c,Value55__c,Value56__c,Value57__c,Value58__c,Value59__c,Value60__c,Value61__c,Value62__c,Value63__c,Value64__c,Value65__c,Value66__c,Value67__c,Value68__c,Value69__c,Value70__c,Value71__c,Value72__c,Value73__c,Value74__c,Value75__c,Value76__c,Value77__c,Value78__c,Value79__c,Value80__c,Value81__c,Value82__c,Value83__c,Value84__c,Value85__c,Value86__c,Value87__c,Value88__c,Value89__c,Value90__c,Template__c, Template__r.Name FROM CallidusDataSource__c dsc where dsc.UserId__c in : userSet and dsc.IsActive__c = true])
	        {
	            contracts = new Sales_Contract__c[userSet.size()];
	            //totalDataSources += src.size();
	            Integer i = 0;
	            for(CallidusDataSource__c sources : src)
	            {
	                  
		            contracts[i] = new Sales_Contract__c();
		            contracts[i].FirstName__c =sources.FirstName__c;
		            contracts[i].Generated_Date__c = dt;
		            contracts[i].LastName__c =sources.LastName__c;
		            if(ripList.size() > 0 && ripList[0].Is_Global_Approvers_Used__c)
		            	contracts[i].Status__c = 'Distributed';
		            else
		            	contracts[i].Status__c = 'Published';
		            contracts[i].UserID__c = sources.UserID__c;
		            contracts[i].User_ID__c = sources.UserID__c;
		            contracts[i].UserRoleId__c = sources.UserRoleId__c;
		            contracts[i].User_Title__c = sources.User_Title__c;
		            contracts[i].UserRoleName__c = sources.UserRoleName__c;
		            contracts[i].TemplateName__c = sources.Template__r.Name;
		            contracts[i].Template__c = sources.Template__c;
		            contracts[i].BatchID__c = batchId;
		            contracts[i].BatchName__c = planGroupName;
		            contracts[i].Batch__c = batchId;
		            contracts[i].is_merge_document__c = true;
		            if(ripList.size() > 0 && ripList[0].Plan_Document_Name__c != null)
		                contracts[i].Plan_Document_Name__c = ripList[0].Plan_Document_Name__c+' '+sources.FirstName__c+' '+sources.LastName__c+' '+dt.month()+'/'+dt.day()+'/'+dt.year();
		            else
		                contracts[i].Plan_Document_Name__c = sources.Template__r.Name+' '+sources.FirstName__c+' '+sources.LastName__c+' 0'+dt.month()+'/'+dt.day()+'/'+dt.year();
		            
			        if(approver.size() > 0 && ripList.size() > 0 && ripList[0].Is_Global_Approvers_Used__c)
		            {
		                contracts[i] = GenerateUtil.populateSalesContractLevels(contracts[i], approver[0], sources.UserID__c);
		            }
	                                
	                contracts[i].Effective_Start_Date__c = sc.Effective_Start_Date__c;
	                contracts[i].Effective_End_Date__c = sc.Effective_End_Date__c;
	                contracts[i].RequiredReturnDate__c = sc.RequiredReturnDate__c;
	                contracts[i] = GenerateUtil.populateNameValuePairs(contracts[i], sources);
	                contracts[i].AttachmentID__c = templateAttachmentMap.get(sources.Template__c);
	                planDocumentsList.add(contracts[i]);
	                i++;
	                planDocsCreated++;
	
	
	            }//end of for(CallidusDataSource__c sources : src)
                insert planDocumentsList;
	
                for(Sales_Contract__c s:planDocumentsList)
                {
                    Sales_Contract__History history = new Sales_Contract__History(ParentId = s.Id);
                    Task t = new Task();
                    t.WhatId = s.Id;
                    if(s.Status__c == 'Distributed')
                    {
                        t.OwnerId = s.Level1__c;
                        t.Subject = 'Plan Document Distributed';
                        t.Description = 'Plan Document Distributed.';
                        t.ActivityDate = s.Level1_Due_Date__c;//Date.valueof(requiredReturnDate);
                        String remDateTime = s.Level1_Due_Date__c+' 08:00:00';
                        t.ReminderDateTime = Datetime.valueof(remDateTime) - 3;
                    }
                    else
                    {
                        t.OwnerId = s.UserID__c;
                        t.Subject = 'Plan Document Published';
                        t.Description = 'Plan Document Published.';
                        t.ActivityDate = s.RequiredReturnDate__c;//Date.valueof(requiredReturnDate);
                        String remDateTime = s.RequiredReturnDate__c+' 08:00:00';
                        t.ReminderDateTime = Datetime.valueof(remDateTime) - 3;
                    }
                    t.Status = 'NotStarted';
                    t.Type = 'Email';
                    t.IsReminderSet = true;
                    t.Priority = 'Normal';
                    
                    tasksList.add(t);

                    if(s.Status__c == 'Distributed')
                    {
                        Approval.ProcessSubmitRequest request = new Approval.ProcessSubmitRequest();
                        request.setObjectId(s.Id);
                        Approval.ProcessResult result = Approval.process(request);
                        
                    }   
                }
                insert tasksList;
	        }//end of for(CallidusDataSource__c[] sources:[SELECT Name,FirstName__c,LastName__c,PayeeID__c,SyncDate__c,UserID__c,UserRoleId__c,UserRoleName__c, Name1__c, Name2__c, Name3__c, Name4__c, Name5__c, Name6__c, Name7__c, Name8__c, Name9__c, Name10__c, Name11__c, Name12__c, Name13__c, Name14__c, Name15__c, Name16__c, Name17__c, Name18__c, Name19__c, Name20__c, Name21__c, Name22__c, Name23__c, Name24__c, Name25__c, Name26__c, Name27__c, Name28__c, Name29__c, Name30__c, Value1__c, Value2__c, Value3__c, Value4__c, Value5__c, Value6__c, Value7__c, Value8__c, Value9__c, Value10__c, Value11__c, Value12__c, Value13__c, Value14__c, Value15__c, Value16__c, Value17__c, Value18__c, Value19__c, Value20__c, Value21__c, Value22__c, Value23__c, Value24__c, Value25__c, Value26__c, Value27__c, Value28__c, Value29__c, Value30__c FROM CallidusDataSource__c dsc where dsc.UserRoleId__c in :tempRoleMap.keyset()])

            batch.Effective_Start_Date__c = sc.Effective_Start_Date__c;
            batch.Effective_End_Date__c = sc.Effective_End_Date__c;
			batch.Name = planGroupName;
            batch.RemainingContracts__c = totalDataSources - planDocsCreated;
            batch.TotalContracts__c = planDocsCreated;
            batch.EndTime__c = datetime.now();
            batch.Status__c = 'Completed';
            update batch;

            DateTime dtn = DateTime.now();
            String subject = 'Plan Document generation '+dtn+' not successful for some users.';
            String textBody = 'Plan Document generation '+dtn+' not successful for some users.';
            String htmlBody = 'Following is the list of users for whom Plan Document generation '+dtn+' was not successful, because their Manager value is not set on their User Record.';
            htmlBody += '<br>';
            for(User u: participantsWithNoManagerAssigned)
            {
                htmlBody += '<br>';
                htmlBody += u.FirstName+', '+u.LastName;
            }
            htmlBody += '<br>';
            htmlBody += '<br>';
            htmlBody += 'Please work with your System Administrator to configure before your next plan document generation.';
            
            if(participantsWithNoManagerAssigned.size() > 0)
            {
                GenerateUtil.sendMailToUser(UserInfo.getUserId(), subject, textBody, htmlBody);
                Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.info, 'Plan Generation was not successful for some of the Users. Email is sent with the details.'));
            }
            else if(participantsWithNoManagerAssigned.size() == 0 && inactiveParticipants.size() == 0)
                Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.info, 'Plan Generation was successful.'));

            subject = 'Plan Generation for some users was  not done as they are inactive.';
            textBody = 'Plan Generation for some users was  not done as they are inactive.';
            htmlBody = 'Following is the list of Inactive users for whom Plan Document Generation was not done.';
            htmlBody += '<br>';
            
            
            for(User u: inactiveParticipants)
            {
                htmlBody += '<br>';
                htmlBody += u.FirstName+', '+u.LastName;
            }
            htmlBody += '<br>';
            htmlBody += '<br>';
            htmlBody += 'Please work with your System Administrator to configure before your next plan document generation.';
            
            if(inactiveParticipants.size() > 0)
            {
                Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.info, 'Plan Generation was not successful for some of the Users as they are inactive. Email is sent with the details.'));
                GenerateUtil.sendMailToUser(UserInfo.getUserId(), subject, textBody, htmlBody);
            }

	        if(planDocumentsList.size()==0)
	        	planDocumentsList = null;
		}
		catch(Exception e)
		{
			Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.info, e.getMessage()));			
		}
		return null;	
	}

}